home *** CD-ROM | disk | FTP | other *** search
- /**
- --
- -- App: QuickDraw GX Shell
- --
- --
- -- Version: 1.0 1/93: added general QuickDraw GX support & scrolling
- -- 1.1 4/93: added support for QuickDraw GX printing and testing to
- -- see is QuickDraw GX is installed.
- --
- --
- -- File: QuickDraw GX Shell (main).c
- --
- -- Comments: This code demonstrates scrolling of a window containing QuickDraw GX shapes.
- -- I create a window in the CreateDocumentWindow function. At this point, I attach a
- -- parent viewPort to the window, and a child viewPort to the parent. This
- -- approach enables our application to accommodiate scroll bars and adjust
- -- the child viewPort's mapping to reflect scrolling of the window's contents.
- --
- -- You might be wondering, why not just perform the same actions on the parent
- -- viewPort attached to the window? You cannot manipulate the viewPort attached
- -- to the window. All of it's attributes are maintained by the QuickDraw GX system.
- -- This leads to a clipping problems because scroll bars are not really part of the
- -- window's definition.
- --
- -- Therefore, we attach the child viewPort to set it's clip shape within the
- -- scroll bars. Also, we update the mapping of this viewPort when the user scrolls,
- -- thereby guaranteeing that all of the shapes are re-drawn in their correct location.
- -- Another approach, would be to update the location of each shape contained in the
- -- window after scrolling. This would require a lot of work on the application's part.
- -- You would also need to undo this operation at print time because your shapes
- -- would not reside in their correct location relative to a page.
- --
- -- If you are interested in finding the QuickDraw GX additions required to run on a
- -- QuickDraw GX system, search for "QuickDraw GX Additions". If you are only
- -- interested in the additions required to support scrolling in a GX world,
- -- search on "QuickDraw GX Scrolling".
- --
- --
- -- Components: QuickDraw GX Shell (main).c
- -- QuickDraw GX Shell (main).h
- -- QuickDraw GX Shell - print.c
- -- QuickDraw GX Shell - print.h
- -- QuickDraw GX Shell - scroll.c
- -- QuickDraw GX Shell - scroll.h
- -- QuickDraw GX Shell (main).π.rsrc
- --
- -- The file titled: "QuickDraw GX - print.c" contains of the code required to
- -- print the contents of the window.
- --
- -- The file titled: "QuickDraw GX Shell - scroll.c" contains of the code required to
- -- maintain, draw, update the scroll bars, and scroll the contents of the window.
- --
- --
- -- QuickDraw GX
- -- Libraries
- -- Used: This application uses the following QuickDraw GX library code files:
- -- "color library.c", "font library.c", "graphics debug library.c",
- -- "layout library.c", "shape library.c", and "transform library.c",
- --
- --
- -- Bugs: If you zoom the window onto a montior which is bigger than the default, you
- -- will receive a GRAPHICS WARNING about how the point does not intersect the
- -- current viewPort. From that point on, until you resize the window to a smaller
- -- size scrolling will not work correctly. You can create this problem by zooming
- -- from an Apple 16" monitor to a portrait monitor. We are currently working on
- -- resolving this problem.
- --
- --
- -- Notes: 1) Print this file in landscape for the best results
- -- 2) If you are using THINK C v5.x, I have added THINK markers to navigate the code.
- -- 3) This code was adapted and simplyified from the "DTS AE Skeleton" sample.
- --
- --
- -- Author: Pete "Luke" Alexander
- -- Developer Technical Support
- -- AppleLink: DEVSUPPORT
- --
- --
- -- ©1992 - 1993 Apple Computer, Inc.
- --
- **/
-
- #include <AppleEvents.h>
- #include <Desk.h>
- #include <Dialogs.h>
- #include <DiskInit.h>
- #include <Errors.h>
- #include <Fonts.h>
- #include <GestaltEqu.h>
- #include <Menus.h>
- #include <Memory.h>
- #include <OSEvents.h>
- #include <OSUtils.h>
- #include <Quickdraw.h>
- #include <Resources.h>
- #include <Script.h>
- #include <StandardFile.h>
- #include <ToolUtils.h>
- #include <Windows.h>
-
- #include "QuickDraw GX Shell (main).h"
- #include "QuickDraw GX Shell - scroll.h"
-
- //
- // The following interface files are for QuickDraw GX.
- //
- #include "font library.h"
- #include "graphics toolbox.h"
- #include "graphics routines.h"
- #include "graphics libraries.h"
- #include "graphics debugging.h"
-
- #include "layout library.h"
- #include "layout routines.h"
- #include "layout feature constants.h"
-
- #include "PrintingManager.h"
-
-
- /* This routine is part of the MPW runtime library. This external
- reference to it is done so that we can unload its segment, %A5Init. */
- #ifndef THINK_C
- extern void _DataInit();
- #endif
-
-
- //
- // Global Variables
- //
- Boolean gDone; /* Has the user selected quit? */
-
-
- //
- // The variables from this point on, were added to support QuickDraw™ GX.
- //
-
- //
- // gGraphicsClient contains the clien we create within the QuickDrawGXInit function.
- //
- gxGraphicsClient gGraphicsClient;
-
- //
- // gthePage contain all of the GX shapes which are displayed in the window. gthePage is defined
- // as a pictureType in the function CreateShapes. CreateShapes creates all of the shapes
- // contained in gthePage.
- //
- gxShape gthePage;
-
- //
- // This viewPort is the child attached to the window's parent viewPort. Since it is a child viewPort,
- // we (the application) need to maintain the clip shape. We also have the ability to manipulate this
- // viewPort as we see fit, therefore we adjust the mapping, to reflect scrolling changes by the user.
- //
- gxViewPort gcontentViewPort;
-
- //
- // gDocumentJob contains the gxJob whihc is used a print time. The boolean gQDGXPrintingInstalled
- // is used to detemrine,if the user has installed printing, if not, we will still run without
- // any printing functionality.
- //
- gxJob gDocumentJob;
- Boolean gQDGXPrintingInstalled = false;
-
- //
- // If gDebugging = TRUE, graphics library errors and notices will be posted. This functionality will only work with
- // the "debugging" version of the Secret Graphics init. If this version of the init is not installed, nothing bad will happen,
- // but these functions will not work. The "debugging" version of the Secret Graphics init is approximately 700K.
- //
- Boolean gDebugging = true;
-
- //
- // Set gGiveMeValidation = TRUE, if you will receive run-time validation.
- //
- Boolean gGiveMeValidation = true;
-
-
- //
- // gGraphicsHeapSize sets the size of the QuickDraw heap created by calling the NewGraphicsClient
- // routine in our QuickDrawGXInit function. You can determine the amount of graphics heap required
- // by using GraphicsBug. In general, you would like to have a few blocks left over. With the
- // QuickDraw GX v1.0b1 build, this app need the gGraphicsHeapSize set to 115k, to receive reliable
- // printing results to the LaserWriter IISC.
- //
- long gGraphicsHeapSize = 115;
-
-
-
- /**----- main --------------------------------------------------------------------------------
- --
- -- Main initializes the application memory, toolbox, menubar, the GX world, and global
- -- variables. We also create a document & window containing our GX picture, which contains
- -- all of our rectangles.
- --
- **/
- main()
- {
- CursHandle theCurs;
-
- #ifndef THINK_C
- UnloadSeg((Ptr) _DataInit); /* note that _DataInit must not be in Main! */
- #endif
-
- ToolBoxInit();
- MenuBarInit();
-
- theCurs = GetCursor(watchCursor);
- SetCursor(*theCurs);
-
- //
- // If QuickDraw GX has not been installed, alert the use aand quit.
- //
- if (!QuickDrawGXInstalled())
- ErrorAlert(kNoQDGXErr, true);
-
- QuickDrawGXInit(); // This function initializes the GX system
-
- gDone = false;
-
- CreateDocumentWindow(nil, "\p Cool QuickDraw GX Shapes? ");
-
- SetCursor(&qd.arrow);
-
- while (!gDone)
- HandleEvent();
-
- ExitToShell();
- }
-
-
- //•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•
- //
- // The following two functions: QuickDrawGXInstalled and QuickDrawGXInit
- //
- // Are used to: determine if QuickDraw GX was installed, and intializing the entire GX world.
- //
- //•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•
-
- /**----- QuickDrawGXInstalled ----------------------------------------------------------------
- --
- -- This function determines, if QuickDraw GX has been installed. If it has everything is
- -- great! Otherwise we will return false to the caller.
- -- (QuickDraw GX Addition)
- **/
- Boolean QuickDrawGXInstalled ()
- {
- long theFeatureInQuestion;
-
- //
- // The QuickDraw GX system requires System 7.1 or newer
- //
- if (Gestalt('grfx', &theFeatureInQuestion) == noErr)
- {
- if (Gestalt('pmgr', &theFeatureInQuestion) == noErr)
- gQDGXPrintingInstalled = true;
- return(true);
- }
- return(false);
- }
-
-
-
- /**----- QuickDrawGXInit ---------------------------------------------------------------------
- --
- -- This function makes all of the calls required to initialize the GX system.
- -- For complete details regarding each call, please see the comment blocks.
- -- (QuickDraw GX Addition)
- --
- **/
- void QuickDrawGXInit(void)
- {
- //
- // The NewGraphicsClient routine defines the QuickDraw GX heap size. If you do not make
- // this call, the GX system will create this heap automatically. How? It will create a
- // QuickDraw GX heap of 600k. This call allows you to explicity define the amount of
- // memory used by the QuickDraw GX system to store it's graphics objects heap.
- //
- // If you do not pass a value for gGraphicsHeapSize, you will receive the default graphics heap.
- // The GX system will automatically page objects to disk when memory is low.
- //
- gGraphicsClient = GXNewGraphicsClient(nil, gGraphicsHeapSize * 1024, 0L);
-
-
- //
- // If gDebugging = TRUE, you will receive graphics library errors, warnings & notices will
- // be posted. This functionality will only work with the "debugging" version of the
- // Secret Graphics init. If this init is not installed, these functions will not work, nor
- // willl anything bad happen. The "debugging" version of the Secret Graphics init is
- // approximately 810K.
- //
- if (gDebugging) {
- SetGraphicsLibraryErrors ();
- SetGraphicsLibraryNotices();
- }
-
- //
- // Set "gGiveMeValidation" to TRUE, if you want run-time validation. As you increase the amount
- // of validation, The drawing speed will SLOW down due to all of the internal checking.
- //
- // gxPublicValidation will check parameters to public routines. For additional details regarding
- // the various levels of validation, please see the documentation.
- //
- if (gGiveMeValidation) GXSetValidation(gxPublicValidation);
-
-
- //
- // Create the default data structures.
- //
- GXEnterGraphics();
-
- //
- // Initailize the GX printing system, if the user has installed it. If the user has not
- // installed the printing system, alert the user to this fact and tell him that drawing
- // into the window will still work, without any printing capabilities.
- //
- if (gQDGXPrintingInstalled)
- gDocumentJob = PrintInit ();
- else ErrorAlert(kNoQDGXPrintingErr, false);
-
-
- //
- // Initialize the common colors library defined in "color library.c" and "graphics library.h".
- // This library is a simple method available for you to color an object quickly by calling the
- // the SetShapeCommonColor(...) function.
- //
- InitCommonColors();
- }
-
-
- //•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•
- //
- // The following four functions: CreateDocumentWindow, CreateThePageOfGXShapes,
- // CreateTextShape, and CreateLayoutShape.
- //
- // Are used to: create a window and attach 2 view ports to the window, create a QuickDraw
- // GX pictures, which contains our text and layout shapes.
- //
- //•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•
-
-
-
- /**----- CreateDocumentWindow ----------------------------------------------------------------
- --
- -- This function creates a new document window. We attached a parent viewPort to the
- -- window and a child viewPort to it. Having the application maintain the child viewPort's
- -- clip shape and mapping will allow use to draw within the scroll bars & update it's
- -- mapping to reflect scrolling of the shapes.
- --
- -- The parameters: we ignore the PicHandle at this point and the str63 containing the
- -- name for the title bar of the window is used.
- --
- -- A boolean is returned indicating success. Failure may result from an running out of
- -- memory in the heap.
- --
- **/
- Boolean CreateDocumentWindow(PicHandle thePicture, Str63 name)
- {
- WindowPtr theWindow;
- ControlHandle hControl, vControl;
- Rect controlRect, deviceRect, windRect, docRect = {0, 0, 1000, 1000};
- Point origin;
-
- /* Allocate space for window */
- theWindow = (WindowPtr)NewPtr(sizeof(MyWindowRecord));
- if (theWindow == nil)
- {
- ErrorAlert(kOutOfMemoryErr, false);
- return(false);
- }
- GetNewWindow(rDocumentWindow, theWindow, (WindowPtr)-1);
-
- ((MyWindowPeek)theWindow)->documentBoundsRect = docRect;
- SetPt(&((MyWindowPeek)theWindow)->origin, 0, 0);
- SetWTitle(theWindow, name);
-
- windRect = ((MyWindowPeek)theWindow)->documentBoundsRect;
-
- windRect.right += kScrollBarWidth-1;
- windRect.bottom += kScrollBarWidth-1;
- OffsetRect(&windRect, -windRect.left, -windRect.top); /* Adjust upper left to 0,0 */
- if (windRect.right < kMinWindowWidth-1) windRect.right = kMinWindowWidth-1;
- if (windRect.bottom < kMinWindowHeight-1) windRect.bottom = kMinWindowHeight-1;
-
- /* Allocate space for HORIZONTAL scroll bar */
- SetRect(&controlRect, 0, 0, 100, 10);
- hControl = NewControl(theWindow, &controlRect, "\p", false, 0, 0, 0, scrollBarProc, 0);
- ((MyWindowPeek)theWindow)->hScrollBar = hControl;
- if (hControl == nil)
- {
- CloseWindow(theWindow);
- DisposePtr((Ptr)theWindow);
- ErrorAlert(kOutOfMemoryErr, false);
- return(false);
- }
-
- /* Allocate space for VERTICAL scroll bar */
- SetRect(&controlRect, 0, 0, 10, 100);
- vControl = NewControl(theWindow, &controlRect, "\p", false, 0, 0, 0, scrollBarProc, 0);
- ((MyWindowPeek)theWindow)->vScrollBar = vControl;
- if (vControl == nil)
- {
- DisposeControl(hControl);
- CloseWindow(theWindow);
- DisposePtr((Ptr)theWindow);
- ErrorAlert(kOutOfMemoryErr, false);
- return(false);
- }
-
- /* POSITION the new window */
- if (FrontWindow() == nil) /* no windows open, use default position */
- { /* Align to upper left of main device */
- OffsetRect(&windRect, 2, 2 + kTitleBarHeight+GetMBarHeight());
- deviceRect = qd.screenBits.bounds;
- deviceRect.left += 3;
- deviceRect.top += 3+GetMBarHeight()+kTitleBarHeight;
- deviceRect.right -= 3;
- deviceRect.bottom -= 3;
- }
- else /* Position down and right from frontmost window */
- {
- SetPort(FrontWindow());
- SetPt(&origin, 0, 0);
- LocalToGlobal(&origin);
- origin.h += kNewWindowOffset;
- origin.v += kNewWindowOffset;
- OffsetRect(&windRect, origin.h, origin.v);
- deviceRect = GetDeviceRect(FrontWindow());
- }
-
- /* Adjust size and position for display */
- /* If not enough room for entire window: */
- /* 1. Position in upper left */
- /* 2. Resize to fit on screen */
- FitWindowOnDevice(&windRect, &deviceRect);
- MoveWindow(theWindow, windRect.left, windRect.top, true);
- SizeWindow(theWindow, windRect.right-windRect.left,
- windRect.bottom-windRect.top, false);
-
- ResizeScrollBars(theWindow); /* Initialize Scroll Bars */
-
- ShowControl(hControl);
- ShowControl(vControl);
- ShowWindow(theWindow);
-
- //
- // We need to attach a couple of viewPorts to the window to allow our
- // QuickDraw GX shapes to be clipped and scrolled correctly.
- // (QuickDraw GX Scrolling)
- //
- {
- gxRectangle viewRect;
- gxViewPort windowParentViewPort;
- gxShape contentViewPortShape;
-
- //
- // Get a rectangle shape which represents the portRect of the window. This
- // shape will be used as the clip shape for the "gcontentViewPort". This
- // viewPort will have all of our QuickDraw GX objects drawn to.
- //
- TranslateWindowBounds(theWindow, &viewRect);
-
- //
- // Adjust our viewRect to accommodate the scroll bars
- //
- viewRect.right -= ff(kScrollBarWidth - 1);
- viewRect.bottom -= ff(kScrollBarWidth - 1);
-
- //
- // Add a viewPort to the window. This will enable the user to move the
- // window around and have our QuickDraw GX objects drawn into this window.
- //
- windowParentViewPort = GXNewWindowViewPort(theWindow);
-
- //
- // Create a second viewPort and attached it to the "parent" viewPort of our
- // window. You cannot manipulate the parent viewPort attached to a window,
- // but you can manipulate it's children. We will manipulate the clip and
- // mapping of this viewPort when the user resizes the window or scrolls it's
- // contents. Also, we need this child viewPort because we want to set the clip
- // shape of the window to reside within the scroll bars, not on top of them,
- // which would be the case if we only used the parent viewPort.
- //
- gcontentViewPort = GXNewViewPort(GXGetViewPortViewGroup(windowParentViewPort));
-
- //
- // Set up the shape, clip and, mapping of our "gcontentViewPort". We will
- // then attached it to the "parent" viewPort of the window.
- //
- contentViewPortShape = GXNewRectangle(&viewRect);
- GXSetViewPortClip(gcontentViewPort, contentViewPortShape);
- GXSetViewPortMapping(gcontentViewPort, nil);
- GXSetViewPortParent(gcontentViewPort, windowParentViewPort);
- GXDisposeShape (contentViewPortShape);
-
- //
- // By calling SetDefaultViewPort (..), all shapes we create will
- // be automatically drawn to "gcontentViewPort".
- //
- SetDefaultViewPort(gcontentViewPort);
-
- gthePage = CreateThePageOfGXShapes (nil);
- }
-
- return(true);
- }
-
-
-
- /**----- CreateThePageOfGXShapes -------------------------------------------------------------
- --
- -- This function creates a GX picture containing the shapes which will be displayed
- -- within our window. In this case, all of the shapes will be rectangles
- -- (QuickDraw GX Addition)
- **/
- gxShape CreateThePageOfGXShapes (gxShape thePage)
- {
- //
- // If the picture passed in has not been created, create an empty GX picture. We set
- // the "uniqueItemsShape" attribute because we are adding the same rectangle multiple
- // times. This guarantees that each rectagnle will have a "unique" reference within
- // the picture. Otherwise, you would only see the last rectangle added to the picture.
- //
- if (thePage == nil)
- {
- thePage = GXNewShape(gxPictureType);
- GXSetShapeAttributes(thePage, gxUniqueItemsShape);
- }
-
- //
- // Create the shapes displayed into the window.
- //
- thePage = CreateTextShape (thePage);
-
- thePage = CreateLayoutShape (thePage);
-
- return (thePage);
- }
-
-
- /**----- CreateTextShape ---------------------------------------------------------------------
- --
- -- This function creates a text shape, converts it to a path shape, and fills it with
- -- a polygon shape which is a star. We will then frame the shape filled with stars.
- -- Finally, we add these two path shapes to the GX picture which was passed into this
- -- function.
- -- (QuickDraw GX Addition)
- **/
- gxShape CreateTextShape (gxShape thePage)
- {
- gxShape tempTextShape;
- gxPoint textPostion = {ff(45),ff(225)};
-
- gxShape starShape;
- gxRectangle starShapeBounds;
- gxPatternRecord starPattern;
-
- long starGeometry[] = { 1, // number of contours
- 5, // number of points
- ff(60), 0, // the points
- ff(90), ff(90),
- 0, ff(30),
- ff(120), ff(30),
- 0, ff(90)};
- //
- // Create the text, set the font, and size.
- //
- tempTextShape = GXNewText(2,(unsigned char*)"GX", &textPostion);
- GXSetShapeTextSize(tempTextShape, ff(250));
-
- SetShapeCommonFont(tempTextShape, newyorkFont); // This call comes from the "font library"
-
-
- //
- // We need to convert our text shape to a path shape. Why? We want to fill our text shape
- // with stars, but you can only fill geometric shapes with other geometric shapes. So, we
- // convert it. We set the shape type, pen, and pen location. We set the pen location to be
- // "gxOutsideFrameStyle" which tells GX graphics to place the pen on the outside of the
- // contour of our path shape. Finally, we set the color of our frame to be magenta. The
- // SetShapeCommonColor call is a library call which creates the magenta color in the RGB
- // color space and colors our shape.
- //
- GXSetShapeType(tempTextShape, gxPathType);
- GXSetShapeFill(tempTextShape, gxClosedFrameFill);
- GXSetShapeStyleAttributes(tempTextShape, gxOutsideFrameStyle);
- GXSetShapePen(tempTextShape, ff(3));
-
- SetShapeCommonColor (tempTextShape, magenta);
-
- //
- // We scale our shape 125% in the x-direction and 65% in the y-direction to get
- // our "GX" path shape to have the fat tall look.
- //
- GXScaleShape(tempTextShape, fl(1.25), fl(0.65), 0, 0);
-
-
- //
- // We add the framed version of our path to our GX picture shape. Anytime, we draw the
- // picture - thePage , the framed path will be drawn. In this case, we add our path
- // to the end of the picture.
- //
- GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, nil);
-
-
- //
- // We change our path's shape fill to be solidFill. Why? When you add a pattern to a shape
- // it fills to the shape fill. Before we changed the fill to solidFill, it was set to frame
- // fill, it would be a little difficult to see the stars with a frame thickness of only 3.
- //
- GXSetShapeFill(tempTextShape, gxSolidFill);
- SetShapeCommonColor (tempTextShape, cold_grey);
-
-
- //
- // Create a star shape which will be used as the fill pattern
- //
- starShape = GXNewPolygons((gxPolygons *) starGeometry);
- GXScaleShape(starShape, fl(0.15), fl(0.15), 0, 0);
-
-
- //
- // Get the bounds of our star shape. We use the bounds to setup the u and v vectors of the pattern
- // record. We want "tempTextShape" to be filled with the stars where each star is placed at edge
- // of the previous star (i.e so the star pattern does not overlap).
- //
- GXGetShapeBounds(starShape, 0L, &starShapeBounds);
-
- //
- // Set up the pattern record containing the star information.
- //
- starPattern.u.x = 0;
- starPattern.u.y = starShapeBounds.bottom;
- starPattern.v.x = starShapeBounds.right + fix1;
- starPattern.v.y = 0;
-
- starPattern.attributes = gxNoAttributes;
- starPattern.pattern = starShape;
-
-
- //
- // Add the star pattern to the style of our "tempTextShape" whihc is now a path and add it
- // to the end of our GX picture - thePage.
- //
- GXSetShapePattern(tempTextShape, &starPattern);
- GXSetPictureParts(thePage, 0, 0, 1, &tempTextShape, nil, nil, nil);
-
- //
- // We can dispose of our star shape because it is now referenced from within the
- // pattern record contained in "gShape".
- //
- GXDisposeShape (starShape);
- GXDisposeShape (tempTextShape);
-
- return (thePage);
- }
-
-
-
- /**----- CreateLayoutShape -------------------------------------------------------------------
- --
- -- This function creates a GX picture containing the shapes which will be displayed
- -- within our window. In this case, all of the shapes will be rectangles
- -- (QuickDraw GX Addition)
- **/
- gxShape CreateLayoutShape (gxShape thePage)
- {
- gxShape tempLayoutShape;
- char *sampleText = "Catch the Nasty WAVE, Dude";
- gxPoint layoutPosition = {ff(45), ff(240)};
-
- gxRunControls runControls;
- gxRunFeature runFeatures[3];
- gxStyle styles[3];
-
- short totalLengthOfLayout,
- lengthsArray[3],
- loop;
-
- //
- // We start by intializing the layout run controls to their default values.
- //
- InitializeRunControls(&runControls);
-
-
- //
- // We need to create the style which will be used for the first run of text within our
- // layout shape: "Catch the Nasty". Within a layout shape, you have the ability to have
- // multiple runs of text. Each run can use: a different font, text size, run features,
- // run controls.
- //
- // In the case of our first run of text, we want to use Hoefler Italic and a text size of 36.
- // We set the run controls to their default setting.
- //
- styles[0] = NewLayoutStyle((char *)"\pHoefler Italic", ff(36), 0, &runControls, nil, 0, nil);
-
-
- //
- // Next, we want to turn on a couple of run features within this run of text. We start by
- // enabling the "as" ligature in "Nasty". We our runFeature we want to set the
- // featureType of our run control to enable the ligature capabilities of Hoefler Italic, and
- // we then enable the "as" ligature.
- //
- runFeatures[0].featureType = gxLigatureType;
- runFeatures[0].featureSelector = gxLigatureRareOnSelector;
-
-
- //
- // The next thing we need to setup our second runFeatures to enable the swash capabilities for
- // our"C", "N", "D" characters contained within the first run of text. These swashes are part of the
- // Hoefler Italic font. We acheive this goal by setting the runFeatures featureType
- // to gxAlternateDesignsType, telling line layout we want swashes for the appropriate
- // characters within this run of text, and we enable the featureSelector
- //
- runFeatures[1].featureType = gxAlternateDesignsType;
- runFeatures[1].featureSelector = gxAlternateDesignsChanceryOnSelector;
-
- //
- // Now we add the two run features to the style used by this run of text:
- //
- GXSetStyleRunFeatures(styles[0], 2, runFeatures);
-
- //
- // In the second style we need to create is for the "WAVE!" run. For this run of text,
- // we want the font to be Times Roman, 38 point text size, and use the default run
- // controls. This style will also give us automatic kerning of the run.
- //
- styles[1] = NewLayoutStyle((char *)"\pTimes Roman", ff(38), 0, &runControls, nil, 0, nil);
-
-
- //
- // The final style we need to create is used by the last run of text "dude".
- //
- styles[2] = NewLayoutStyle((char *)"\pHoefler Italic", ff(40), 0, &runControls, nil, 0, nil);
-
- //
- // The third run features used for the style reference by the last run of text will
- // enable the final form of "e" in "dude". We enable these smartSwashType feature and
- // turn on the final form of "e".
- //
- runFeatures[2].featureType = gxSmartSwashType;
- runFeatures[2].featureSelector = gxSmartSwashLineFinalsOnSelector;
-
-
- //
- // Update the style used for this run of text to use the our run features which
- // enable the final form "e".
- //
- GXSetStyleRunFeatures(styles[2], 3, runFeatures);
-
-
- lengthsArray[0] = 15; lengthsArray[1] = 6; lengthsArray[2] = 5;
-
- totalLengthOfLayout = 26;
-
- //
- // We now have all the information required to define our layout shape and add
- // it to our picture stored in the variable gthePage. Our layout shape will contain
- // three runs of text using three different styles. Each style will use a different
- // text size. Two different fonts will be used, and three run features will be enabled.
- // The definition looks like this:
- //
- tempLayoutShape = GXNewLayout( 1,
- &totalLengthOfLayout,
- (void *) &sampleText,
- 3,
- lengthsArray,
- styles,
- 0, nil, nil, nil, &layoutPosition);
-
- GXSetPictureParts(thePage, 0, 0, 1, &tempLayoutShape, nil, nil, nil);
-
-
- GXSkewShape(tempLayoutShape, fl(1.25), 0, layoutPosition.x, layoutPosition.y);
- GXMoveShape (tempLayoutShape, ff(15), ff(75));
-
- GXSetPictureParts(thePage, 0, 0, 1, &tempLayoutShape, nil, nil, nil);
-
- //
- // Dispose of all of the QuickDraw GX objects which are no longer needed.
- //
- GXDisposeShape (tempLayoutShape);
-
- for (loop = 0; loop <= 2; loop++)
- GXDisposeStyle(styles[loop]);
-
- return (thePage);
- }
-
-
-
- //•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•
- //
- // The following two functions: TranslateWindowBounds and ResetContentViewPortClip
- //
- // Are utility functions used by this application to work between the QuickDraw based
- // window world and QuickDraw GX viewPort world. TranslateWindowBounds converts the
- // QuickDraw portRect to a QuickDraw GX fixed point rectangle and ResetContentViewPortClip
- // resets the content's viewPort clip (i.e. the child viewport attached to the parent window
- // viewport).
- //
- //•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•
-
-
- /**----- TranslateWindowBounds ---------------------------------------------------------------
- --
- -- This function returns a fixed point rectangle which represents the portRect of the
- -- window. The shape returned is used as the new clip shape for the gcontentViewPort.
- --
- -- (QuickDraw GX Scrolling)
- **/
- void TranslateWindowBounds(WindowPtr myWindow, gxRectangle *boundingBoxPtr)
- {
- GrafPtr oldPort;
- Rect qdBounds;
- gxRectangle gxBounds;
-
- GetPort(&oldPort);
- SetPort(myWindow);
-
- qdBounds = myWindow->portRect; // this is in globals coordinates
-
- //
- // Convert the QuickDraw rectangle into a QuickDraw GX fixed point rectangle.
- //
- GXQDGlobalToFixedLocal((Point *) &qdBounds.top, (gxPoint *) &gxBounds.left );
- GXQDGlobalToFixedLocal((Point *) &qdBounds.bottom, (gxPoint *) &gxBounds.right );
-
- *boundingBoxPtr = gxBounds;
-
- SetPort(oldPort);
- }
-
-
-
- /**----- ResetContentViewPortClip ------------------------------------------------------------
- --
- -- This function resets the clip shape of the "gcontentViewPort", to represent the new
- -- clip shape after the user has zoomed or resized the window.
- -- (QuickDraw GX Scrolling)
- **/
- void ResetContentViewPortClip (WindowPtr theWindow)
- {
- gxRectangle viewRect;
- gxShape contentViewPortClipShape;
-
- //
- // Return a fixed point rectangle in "viewRect" which represents the portRect of the
- // window. This shape will be used as the new clip shape for "gcontentViewPort".
- TranslateWindowBounds(theWindow, &viewRect);
-
- //
- // Adjust our viewRect to accommodate the scroll bars
- //
- viewRect.right -= ff(kScrollBarWidth - 1);
- viewRect.bottom -= ff(kScrollBarWidth - 1);
-
- //
- // Create and set the new clip shape.
- //
- contentViewPortClipShape = GXNewRectangle(&viewRect);
- GXSetViewPortClip(gcontentViewPort, contentViewPortClipShape);
-
- GXDisposeShape (contentViewPortClipShape);
- }
-
- //•-• End QuickDraw GX Utilities •-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•-•
-
-
-
-
-
- /**----- ToolBoxInit -------------------------------------------------------------------------
- --
- -- This function initializes the toolbox.
- --
- **/
- void ToolBoxInit(void)
- {
- EventRecord theEvent;
- short count;
-
- /** Generic heap initialization. **/
- MaxApplZone();
- MoreMasters(); MoreMasters(); MoreMasters();
- MoreMasters(); MoreMasters(); MoreMasters();
-
- InitGraf (&qd.thePort);
- InitFonts ();
- FlushEvents(everyEvent, 0);
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
-
- /* Multi-finder brings our application to the front after */
- /* we ask for three events. */
- for (count=3; count!=0; count--)
- EventAvail(everyEvent, &theEvent);
- }
-
-
- /**----- MenuBarInit -------------------------------------------------------------------------
- --
- -- This function initializes the menus, and installs DAs in the Apple Menu.
- --
- **/
- void MenuBarInit(void)
- {
- Handle theMenuBar;
- MenuHandle appleMenu;
-
- /* Install menus from resources */
- theMenuBar = GetNewMBar(rMenuBar);
- if (theMenuBar == nil)
- ErrorAlert(kNoMenuBarErr, true);
- SetMenuBar(theMenuBar);
- DisposHandle(theMenuBar);
-
- /* Add desk accessories to Apple Menu */
- appleMenu = GetMHandle(mApple);
- if (appleMenu != nil)
- AddResMenu(appleMenu, kDriverType);
-
- DrawMenuBar();
- }
-
-
-
- /**----- HandleEvent -------------------------------------------------------------------------
- --
- -- This function contains the main event loop.
- --
- **/
- void HandleEvent(void)
- {
- EventRecord theEvent;
- OSErr myErr;
- WindowPtr theWindow;
-
- WaitNextEvent(everyEvent, &theEvent, 30, nil);
-
- switch (theEvent.what)
- {
- case mouseDown:
- HandleMouseDown(&theEvent);
- break;
-
- case keyDown:
- case autoKey:
- HandleKeyPress(&theEvent);
- break;
-
- case updateEvt:
- theWindow = (WindowPtr)theEvent.message;
- BeginUpdate(theWindow);
- if (!EmptyRgn(theWindow->visRgn))
- {
- SetPort(theWindow);
- UpdtControl(theWindow, theWindow->visRgn);
- DrawGrowIcon(theWindow);
- DrawWindow(theWindow);
- }
- EndUpdate(theWindow);
-
- case diskEvt:
- HandleDiskEvent(&theEvent);
- break;
-
- case activateEvt:
- ActivateWindow((WindowPtr)theEvent.message, theEvent.modifiers & activeFlag);
- break;
-
- case osEvt:
- HandleOSEvent(&theEvent);
- break;
-
- case kHighLevelEvent:
- myErr = AEProcessAppleEvent(&theEvent);
- if (myErr != noErr)
- {
- ErrorAlert(kAppleEventErr, false);
- }
- break;
- }
- }
-
-
- /**----- HandleMouseDown ---------------------------------------------------------------------
- --
- -- This functions is called whenever the mouse button is pressed. It finds the mouse
- -- location when the button was pressed and routes the event appropriately.
- --
- **/
- void HandleMouseDown(EventRecord *theEvent)
- {
- short thePart;
- WindowPtr theWindow;
- Rect theRect;
- short controlPart;
- ControlHandle theControl;
-
- thePart = FindWindow(theEvent->where, &theWindow);
- switch (thePart)
- {
- case inMenuBar:
- AdjustMenus();
- DoMenu(MenuSelect(theEvent->where));
- break;
-
- case inSysWindow:
- SystemClick(theEvent, theWindow);
- break;
-
- case inContent:
- if (theWindow != FrontWindow())
- SelectWindow(theWindow);
- else
- {
- SetPort(theWindow);
- GlobalToLocal(&theEvent->where);
- controlPart = FindControl(theEvent->where, theWindow, &theControl);
- if (controlPart != 0)
- DoControl(theEvent->where, theControl, controlPart);
- }
- break;
-
- case inDrag:
- if (theWindow != FrontWindow())
- SelectWindow(theWindow);
- theRect = (**GetGrayRgn()).rgnBBox;
- DragWindow(theWindow, theEvent->where, &theRect);
- break;
-
- case inGrow:
- DoGrowWindow(theWindow, theEvent->where);
- break;
-
- case inGoAway:
- if (TrackGoAway(theWindow, theEvent->where))
- ShutdownProgram();
- break;
-
- case inZoomIn:
- case inZoomOut:
- if (TrackBox(theWindow, theEvent->where, thePart))
- DoZoomWindow(theWindow, thePart);
- break;
- }
- }
-
-
- /**----- DoGrowWindow ------------------------------------------------------------------------
- --
- -- This function takes care of growing a window after the mouse has been pressed over
- -- the grow icon. It allows maximum growth of the document size or display size, whichever
- -- is smaller. It allows minimum growth to (kMinWindowWidth,kMinWindowHeight) or the
- -- document size, whichever is larger. Finally, it adjusts and redraws the scroll bars
- -- for the new window size.
- --
- **/
- void DoGrowWindow(WindowPtr theWindow, Point where)
- {
- Rect growRect, windRect;
- Rect thePage;
- short width, height;
- long newSize;
- Point origin;
-
- thePage = ((MyWindowPeek)theWindow)->documentBoundsRect;
-
- width = thePage.right - thePage.left + kScrollBarWidth;
- height = thePage.bottom - thePage.top + kScrollBarWidth;
-
- growRect = (**GetGrayRgn()).rgnBBox;
- if (theWindow->portRect.left + width < growRect.right)
- growRect.right = theWindow->portRect.left + width;
-
- if (theWindow->portRect.top + height < growRect.bottom)
- growRect.bottom = theWindow->portRect.top + height;
-
- // Minimum size is (kMinWindowWidth,kMinWindowHeight)
- growRect.left = kMinWindowWidth;
- growRect.top = kMinWindowHeight;
-
- // Make sure maximum size is at least minimum size
- if (growRect.right < growRect.left) growRect.right = growRect.left;
- if (growRect.bottom < growRect.top) growRect.bottom = growRect.top;
-
- /* Allow user to grow the window, then resize it */
- newSize = GrowWindow(theWindow, where, &growRect);
-
- if (newSize != 0)
- {
- GrafPtr saveport;
-
- InvalidateScrollBars(theWindow);
- SizeWindow(theWindow, LoWord(newSize), HiWord(newSize), true);
- InvalidateScrollBars(theWindow);
- ResizeScrollBars(theWindow);
-
- //
- // The user as grown the window, we need to update the clip shape of the contentviewPort
- // we attached to the window earlier in the CreateDocumentWindow function. If we did not
- // update the clip shape of the contentviewPort clip, we would draw through the scroll
- // bars on the next update event. (QuickDraw GX Scrolling)
- //
- ResetContentViewPortClip(theWindow);
-
-
- /* reposition document */
- origin = ((MyWindowPeek)theWindow)->origin;
- width = theWindow->portRect.right - theWindow->portRect.left - origin.h - width + 1;
- height = theWindow->portRect.bottom - theWindow->portRect.top - origin.v - height + 1;
- if (width < 0) width = 0;
- if (height < 0) height = 0;
-
- if ( (width > 0) || (height > 0) )
- {
- DoScroll(theWindow, width, height);
- ResizeScrollBars(theWindow);
- }
- }
- }
-
-
- /**----- DoZoomWindow ------------------------------------------------------------------------
- --
- -- This function zooms a window. It follows the new human interface guidelines be
- -- dealing with multiple displays. To do this, every time the window is zoomed to the
- -- standard state, it recalculates the standard state based on the display that contains
- -- the largest area of the window. This routine was adapted from Macintosh Technical
- -- Note #79: "_ZoomWindow".
- --
- **/
- void DoZoomWindow(WindowPtr theWindow, short thePart)
- {
- Rect deviceRect, zoomRect;
- Point offset;
- WStateDataHandle windowState;
-
- SetPort(theWindow);
- EraseRect(&theWindow->portRect);
- if ( (thePart == inZoomOut) && (ColorQDAvail()) )
- {
- /* Get window location in global coordinates */
- SetPt(&offset, 0, 0);
- LocalToGlobal(&offset);
-
- deviceRect = GetDeviceRect(theWindow);
-
- zoomRect = ((MyWindowPeek)theWindow)->documentBoundsRect;
- zoomRect.right += kScrollBarWidth-1;
- zoomRect.bottom += kScrollBarWidth-1;
-
- OffsetRect(&zoomRect, -zoomRect.left, -zoomRect.top); /* Adjust upper left to 0,0 */
-
- /* At least minimum window size */
- if (zoomRect.right < kMinWindowWidth-1) zoomRect.right = kMinWindowWidth-1;
- if (zoomRect.bottom < kMinWindowHeight-1) zoomRect.bottom = kMinWindowHeight-1;
-
- OffsetRect(&zoomRect, offset.h, offset.v); /* Align to window */
-
- FitWindowOnDevice(&zoomRect, &deviceRect);
-
- windowState = (WStateDataHandle)((WindowPeek)theWindow)->dataHandle;
- (**windowState).stdState = zoomRect;
- }
- ZoomWindow(theWindow, thePart, true);
- InvalRect(&theWindow->portRect);
-
- ResizeScrollBars(theWindow);
-
- //
- // The user as grown the window, we need to update the "gcontentviewPort" we attached to
- // the window earlier in the CreateDocumentWindow (..) function. If we did not update, the
- // contentviewPort clip, we would draw through the scroll bars on the next update event.
- // (QuickDraw GX Scrolling)
- //
- ResetContentViewPortClip(theWindow);
- }
-
-
-
- /**----- FitWindowOnDevice -------------------------------------------------------------------
- --
- -- This routine takes two rectangles as parameters. windRect is the location of the
- -- window in global coordinates. deviceRect is the boundary of the device in global
- -- coordinates. This routine fits windRect inside deviceRect. windRect is modified,
- -- and upon completion, is where the window should be positioned.
- --
- -- Here's how the algorithm works:
- -- Attempt to leave the window in the same location. If the window doesn't fit inside
- -- the deviceRect, move it to the upper left corner of deviceRect. If the window still
- -- doesn't fit, resize windRect to fit inside the maxRect.
- --
- -- NOTE: Both rectangles must be in the same coordinate system.
- --
- **/
- void FitWindowOnDevice(Rect *windRect, Rect *deviceRect)
- {
- Rect theUnion;
-
- UnionRect(windRect, deviceRect, &theUnion);
- if (!EqualRect(deviceRect, &theUnion)) /* window contained on screen? */
- { /* no, move to upper left corner of maxRect */
- OffsetRect(windRect, deviceRect->left-windRect->left, deviceRect->top-windRect->top);
- UnionRect(windRect, deviceRect, &theUnion);
- if (!EqualRect(deviceRect, &theUnion)) /* window contained on screen? */
- { /* no, resize window to fit */
- if (windRect->right > deviceRect->right)
- windRect->right = deviceRect->right;
- if (windRect->bottom > deviceRect->bottom)
- windRect->bottom = deviceRect->bottom;
- }
- }
- }
-
-
- /**----- GetDeviceRect -----------------------------------------------------------------------
- --
- -- This routine takes a WindowPtr as its parameter. It returns the boundary rectangle of
- -- the device that contains the largest area of that window. The rect is returned in
- -- global coordinates.
- --
- **/
- Rect GetDeviceRect(WindowPtr theWindow)
- {
- Rect deviceRect, windRect, theSect;
- GDHandle nthDevice, dominantGDevice;
- long sectArea, greatestArea;
- short bias;
- Point offset;
-
- /* Get portRect in global coordinates */
- windRect = theWindow->portRect;
- SetPt(&offset, 0, 0);
- LocalToGlobal(&offset);
- OffsetRect(&windRect, offset.h, offset.v);
-
- bias = kTitleBarHeight;
- windRect.top -= bias;
-
- /* This loop checks the window against all the gdRects in the gDevice list */
- /* and remembers which gdRect contains the largest portion of the window */
- /* being zoomed. */
- nthDevice = GetDeviceList();
- greatestArea = 0;
- while (nthDevice != nil)
- {
- if (TestDeviceAttribute(nthDevice, screenDevice))
- if (TestDeviceAttribute(nthDevice, screenActive))
- {
- SectRect(&windRect, &(**nthDevice).gdRect, &theSect);
- sectArea = (long)(theSect.right - theSect.left) *
- (theSect.bottom - theSect.top);
- if (sectArea > greatestArea)
- {
- greatestArea = sectArea;
- dominantGDevice = nthDevice;
- }
- }
- nthDevice = GetNextDevice(nthDevice);
- }
-
- /* Create a max zoom rectangle, accounting for menu bar height if on main screen */
- if (dominantGDevice == GetMainDevice())
- bias += GetMBarHeight();
- SetRect(&deviceRect, (**dominantGDevice).gdRect.left+3,
- (**dominantGDevice).gdRect.top+bias+3,
- (**dominantGDevice).gdRect.right-3,
- (**dominantGDevice).gdRect.bottom-3);
-
- return(deviceRect);
- }
-
-
- /**----- HandleKeyPress ----------------------------------------------------------------------
- --
- -- This function is called whenever a key is pressed. Since this program has no typed
- -- input, we are only concerned about command key equivalent menu selections.
- --
- **/
- void HandleKeyPress(EventRecord *theEvent)
- {
- char theChar;
-
- theChar = theEvent->message & charCodeMask;
- if ((theEvent->modifiers & cmdKey)!=0)
- {
- AdjustMenus();
- DoMenu(MenuKey(theChar));
- }
- }
-
-
-
- /**----- HandleDiskEvent ---------------------------------------------------------------------
- --
- -- This function checks whether the disk was successfully mounted. If it wasn't, the disk
- -- initialization package is invoked.
- --
- **/
- void HandleDiskEvent(EventRecord *event)
- {
- Point thePoint = {120, 120};
-
- if (HiWord(event->message) != noErr)
- {
- DILoad();
- DIBadMount(thePoint, event->message); /* thePoint is ignored in sys 7+ */
- DIUnload();
- }
- }
-
-
- /**----- HandleOSEvent -----------------------------------------------------------------------
- --
- -- This function is called when OSEvents are received. It handles suspend, resume, and mouse
- -- moved OSEvents.
- --
- **/
- void HandleOSEvent(EventRecord *theEvent)
- {
- WindowPtr theWindow;
-
- switch ((theEvent->message >> 24) & 0x000000ff)
- {
- case suspendResumeMessage:
- if (theEvent->message & 0x00000001) /* resume message */
- {
- SetCursor(&qd.arrow);
- theWindow = FrontWindow();
- if (theWindow != nil)
- ActivateWindow(theWindow, true); /* Activate front window */
- /* Copy contents of clipboard (if changed) to private scrap */
- }
- else /* suspend message */
- {
- theWindow = FrontWindow();
- if (theWindow != nil)
- ActivateWindow(theWindow, false); /* Deactivate front window */
- /* Move private scrap to clipboard */
- }
- break;
-
- case mouseMovedMessage:
- break;
- }
- }
-
-
- /**----- CloseFrontWindow --------------------------------------------------------------------
- --
- -- This function closes the frontmost window and disposes of the window record allocated
- -- on the heap for it.
- --
- **/
- void CloseFrontWindow(void)
- {
- WindowPtr theWindow;
-
- theWindow = FrontWindow();
- if (theWindow!=nil)
- {
- CloseWindow(theWindow);
- DisposePtr((Ptr)theWindow);
- }
- }
-
-
-
- /**----- DrawWindow --------------------------------------------------------------------------
- --
- -- This function draws the contents of the window without overwriting the scroll bars.
- --
- **/
- void DrawWindow(WindowPtr theWindow)
- {
- PicHandle thePicture;
- Rect tempRect;
- Point origin;
- RgnHandle saveClip;
-
- SetPort(theWindow);
-
- saveClip = NewRgn(); /* Remove scroll bar areas from clipRgn */
- GetClip(saveClip);
- tempRect = theWindow->portRect;
- tempRect.right -= (kScrollBarWidth-1);
- tempRect.bottom -= (kScrollBarWidth-1);
- ClipRect(&tempRect);
-
- SetClip(saveClip); /* Restore clipRgn */
- DisposeRgn(saveClip);
-
- //
- // Draw the shapes contained within our GX picture shape - gthePage (QuickDraw GX Addition)
- //
- GXDrawShape (gthePage);
- }
-
-
- /**----- ActivateWindow ----------------------------------------------------------------------
- --
- -- This function activates or deactivates a window, and is called when either an
- -- activate/deactivate event or suspend/resume event is received. The parameters are a
- -- window pointer to the desired window, and a boolean specifying whether to activate
- -- or deactivate the window.
- **/
- void ActivateWindow(WindowPtr theWindow, Boolean activate)
- {
- if (theWindow == nil) /* safety check */
- return;
-
- if (activate) /* activiate window */
- {
- /* Highlight controls */
- DrawGrowIcon(theWindow);
- HiliteControl(((MyWindowPeek)theWindow)->vScrollBar, 0);
- HiliteControl(((MyWindowPeek)theWindow)->hScrollBar, 0);
- /* Restore vertical bar or highlighting */
- /* Enable appropriate menu items */
- }
- else /* deactivate window */
- {
- /* Unhighlight controls */
- DrawGrowIcon(theWindow);
- HiliteControl(((MyWindowPeek)theWindow)->vScrollBar, 255);
- HiliteControl(((MyWindowPeek)theWindow)->hScrollBar, 255);
- /* Remove vertical bar or highlighting */
- /* Disable appropriate menu items */
- }
- }
-
-
-
- /**----- DoMenu ------------------------------------------------------------------------------
- --
- -- This function is called when a menu item has been selected either with the mouse,
- -- or a keyboard equivalent.
- --
- **/
- void DoMenu(long menuChoice)
- {
- short theMenu;
- short theItem;
- MenuHandle appleMenu;
- Str255 accName;
- GrafPtr savePort;
-
- theMenu = HiWord(menuChoice);
- theItem = LoWord(menuChoice);
-
- switch (theMenu)
- {
- case mApple:
- if (theItem == iAbout)
- Alert(rAboutBox, (ModalFilterProcPtr)nil);
- else
- {
- appleMenu = GetMHandle(mApple);
- if (appleMenu != nil)
- {
- GetItem(appleMenu, theItem, accName); /* Call desk accessory */
- GetPort(&savePort);
- OpenDeskAcc(accName);
- SetPort(savePort);
- }
- }
- break;
-
- case mFile:
- switch (theItem)
- {
- case iOpen:
- break;
-
- case iClose:
- break;
-
- case iPrintOneCopy:
- DoPrintOneCopy (FrontWindow(), gDocumentJob, gthePage);
- break;
-
- case iDocumentSetup:
- DoDocumentSetupCommand(gDocumentJob);
- break;
-
- case iPageSetup:
- break;
-
- case iPrint:
- DoPrintCommand(FrontWindow(), gDocumentJob, gthePage);
- break;
-
- case iQuit:
- ShutdownProgram();
- break;
- }
- break;
- }
- HiliteMenu(0);
- }
-
-
-
- /**----- AdjustMenus -------------------------------------------------------------------------
- --
- -- This function is called immediately before each time the user makes a menu selection.
- -- It enables/disables the appropriate menu items based on the current state of the
- -- program. In version 1.0, we do not update the menus. We only support "quit".
- **/
- void AdjustMenus(void)
- {
- WindowPtr myWindow;
- MenuHandle myFileMenu;
-
- myFileMenu = GetMHandle (mFile);
-
- myWindow = FrontWindow ();
-
- if (!myWindow && gQDGXPrintingInstalled)
- {
- DisableItem (myFileMenu, iPrintOneCopy);
- DisableItem (myFileMenu, iDocumentSetup);
- DisableItem (myFileMenu, iPrint);
- } else if (gQDGXPrintingInstalled)
- {
- EnableItem (myFileMenu, iPrintOneCopy);
- EnableItem (myFileMenu, iDocumentSetup);
- EnableItem (myFileMenu, iPrint);
- }
- }
-
-
-
- /**----- ColorQDAvail ------------------------------------------------------------------------
- --
- -- This function is used before calling Color QuickDraw routines to see if they are
- -- available. Note that MPW 3.2 and THINK C 5.0 both include glue that let you use
- -- Gestalt even if it is not in ROM or in the System File. If you are not using one of
- -- these environments, and you don't have Gestalt glue, you will need to use the
- -- TrapAvailable check (as shown in Inside Macintosh VI 3-8) to determine whether the
- -- Gestalt call exists before calling it.
- --
- **/
- Boolean ColorQDAvail(void)
- {
- long response;
-
- if (Gestalt(gestaltQuickdrawVersion, &response) == noErr)
- if ((response & 0x0000ffff) >= gestalt8BitQD)
- return(true);
- return(false);
- }
-
-
-
- /**----- ErrorAlert --------------------------------------------------------------------------
- --
- -- This function displays an error message in an alert. The error number corresponds
- -- to an error message in a 'str#' resource. This message is displayed in a dialog box.
- -- The Boolean parameter is true for a fatal error, and will cause the program to
- -- immediately terminate instead of returning.
- --
- **/
- void ErrorAlert(short errNumber, Boolean fatal)
- {
- Str255 errorString;
-
- GetIndString(errorString, rErrorStrings, errNumber);
-
- ParamText(errorString, "\p", "\p", "\p");
- if (fatal)
- {
- StopAlert(rFatalErrorAlert, nil);
- ExitToShell();
- }
- else
- NoteAlert(rNonFatalErrorAlert, nil);
- }
-
-
-
- /**----- ShutdownProgram ---------------------------------------------------------------------
- --
- -- This function is called before normal termination of the program. It sets the event
- -- loop done variable to true, so the program will exit at the end of the event loop. We
- -- call CloseFrontWindow() to dispose of our window and data structure containing our
- -- document information.
- --
- -- If this program had editing capabilities, this is where the user would be asked if
- -- he wanted to save any changed documents before quitting.
- --
- **/
- void ShutdownProgram(void)
- {
- WindowPtr theWindow;
-
- gDone = true;
-
- //
- // If we created a GX picture which contains our window full of information, we wnat to
- // dispose of it, by callling DisposeShape. We call DisposeCommonColor () because we
- // initialized the common colors library earlier in the QuickDrawGXInit function.
- // (QuickDraw GX Addition)
- if (gthePage != nil) GXDisposeShape(gthePage);
-
- DisposeCommonColors();
-
- //
- // This function call will dispose of the data contained in the window.
- //
- CloseFrontWindow();
-
- //
- // If printing was installed by the user, we want to dispose of the "job" we created
- // when we initialized the QuickDraw GX printing system.
- //
- if (gQDGXPrintingInstalled) TermintatePrintLand(gDocumentJob);
-
- //
- // Deallocate all of the default data and memory structures for the QuickDraw GX
- // graphics and layout system. (QuickDraw GX Addition)
- //
- GXExitGraphics();
- GXDisposeGraphicsClient(gGraphicsClient);
- }
-